Read in the labelled object Run the correlation comparison between the total scRNA per FACS pop and the AB levels Calculate the proportion of the cell types from the orginal labels UMAP of the cell POPS merged UMAP of the subtypes labelled


library(Seurat)
Attaching SeuratObject
Attaching sp
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library('reshape')

Attaching package: ‘reshape’

The following object is masked from ‘package:dplyr’:

    rename
library("ggplot2")

Read in the lableled object single cell sequencing

saveRDS(seu.sc,,paste(pathway, "CombinedLabeledMarkers14102022.RDS"))
Error in saveRDS(seu.sc, , paste(pathway, "CombinedLabeledMarkers14102022.RDS")) : 
  'file' must be non-empty string
NA

Read in the Flow Cytometry data

output_path = "/Users/rhalenathomas/Documents/Data/FlowCytometry/PhenoID/Analysis/PaperFigures/PostSortGatingPops/"
seu.fc <- readRDS(paste(output_path,"june10postSort.seu.RDS", sep = ""))
unique(seu.fc$GatedPop)
[1] Astrocytes RadialGlia Neurons1   Neurons2  
Levels: Astrocytes RadialGlia Neurons1 Neurons2

Marker list


marker.ab <- c("CD24","CD56","CD29","CD15","CD184","CD133","CD71","CD44","GLAST","AQP4","HepaCAM", "CD140a","O4")

marker.genes <-c("CD24","NCAM1","ITGB1","FUT4","CXCR4","PROM1","TFRC","CD44","SLC1A3","AQP4","HEPACAM", "PDGFRA","NKX6-2")

Make the expression matrixes

seu.sc <- ScaleData(object = seu.sc, features = rownames(seu.sc))
Centering and scaling data matrix

  |                                                                                               
  |                                                                                         |   0%
  |                                                                                               
  |===                                                                                      |   3%
  |                                                                                               
  |=====                                                                                    |   6%
  |                                                                                               
  |========                                                                                 |   9%
  |                                                                                               
  |==========                                                                               |  12%
  |                                                                                               
  |=============                                                                            |  15%
  |                                                                                               
  |================                                                                         |  18%
  |                                                                                               
  |==================                                                                       |  21%
  |                                                                                               
  |=====================                                                                    |  24%
  |                                                                                               
  |========================                                                                 |  26%
  |                                                                                               
  |==========================                                                               |  29%
  |                                                                                               
  |=============================                                                            |  32%
  |                                                                                               
  |===============================                                                          |  35%
  |                                                                                               
  |==================================                                                       |  38%
  |                                                                                               
  |=====================================                                                    |  41%
  |                                                                                               
  |=======================================                                                  |  44%
  |                                                                                               
  |==========================================                                               |  47%
  |                                                                                               
  |============================================                                             |  50%
  |                                                                                               
  |===============================================                                          |  53%
  |                                                                                               
  |==================================================                                       |  56%
  |                                                                                               
  |====================================================                                     |  59%
  |                                                                                               
  |=======================================================                                  |  62%
  |                                                                                               
  |==========================================================                               |  65%
  |                                                                                               
  |============================================================                             |  68%
  |                                                                                               
  |===============================================================                          |  71%
  |                                                                                               
  |=================================================================                        |  74%
  |                                                                                               
  |====================================================================                     |  76%
  |                                                                                               
  |=======================================================================                  |  79%
  |                                                                                               
  |=========================================================================                |  82%
  |                                                                                               
  |============================================================================             |  85%
  |                                                                                               
  |===============================================================================          |  88%
  |                                                                                               
  |=================================================================================        |  91%
  |                                                                                               
  |====================================================================================     |  94%
  |                                                                                               
  |======================================================================================   |  97%
  |                                                                                               
  |=========================================================================================| 100%

Calculate correlation between two matrixes

df.cor
           Astrocytes RadialGlia   Neurons1    Neurons2
Astrocytes  0.5553328  0.1522878 -0.4517431 -0.18064326
RadialGlia  0.1305815  0.4451073 -0.3314321  0.05559489
Neurons1   -0.4098105 -0.3016957  0.4534910  0.05175022
Neurons2   -0.4858683 -0.1624758  0.3770386  0.23752196
write.csv(df.cor, paste(output_path,"CorrelationsFCscRNAseq.csv"))

Plot the heatmap Figure 6A

# need to melt the matrix
longData<- melt(df.cor)
Warning in type.convert.default(X[[i]], ...) :
  'as.is' should be specified by the caller; using TRUE
Warning in type.convert.default(X[[i]], ...) :
  'as.is' should be specified by the caller; using TRUE
head(longData)
colnames(longData) <- c("FC","scRNA","R2")

ggplot(longData, aes(x=scRNA,y=FC, fill =R2)) + geom_tile() +
  scale_fill_gradient2(low = "#075AFF",
                       mid = "#FFFFCC",
                       high = "#FF0000") +
   guides(fill = guide_colourbar(label = TRUE,
                                ticks = FALSE)) + theme_bw() +
  coord_fixed()  +scale_x_discrete(expand=c(0,0))+
  scale_y_discrete(expand=c(0,0))+ theme(text = element_text(size=16, colour = "black"),
        axis.text.x = element_text(size = 18, colour = "black", angle = 90), axis.text.y = element_text(size= 18, colour = "black"))  + xlab('scRNAseq') + ylab('Flow Cytometry') 

output_path <- "/Users/rhalenathomas/Documents/Projects_Papers/PhenoID/ForFigures/scRNA/"

pdf(paste(output_path,"FC_scRNA_correlationOct16.pdf"), width = 8, height = 5)
ggplot(longData, aes(x=scRNA,y=FC, fill =R2)) + geom_tile() +
  scale_fill_gradient2(low = "#075AFF",
                       mid = "#FFFFCC",
                       high = "#FF0000", midpoint = 0, limit = c(-0.5,0.5)) +
   guides(fill = guide_colourbar(label = TRUE,
                                ticks = FALSE)) + theme_bw() +
  coord_fixed()  +scale_x_discrete(expand=c(0,0)) +
  scale_y_discrete(expand=c(0,0)) + 
  theme(text = element_text(size=16, colour = "black"),
        axis.text.x = element_text(size = 16, colour = "black", angle = 90), axis.text.y = element_text(size= 16, colour = "black"))  + xlab('scRNAseq') + ylab('Flow Cytometry') 

dev.off()
quartz_off_screen 
                2 

Compare proportions of cells in each FACS pop - Figure 6B

Make a table of cell types


library(stringr)
library(reshape)

# for original cell types 


df.r <- reshape(df, idvar = "Var2", timevar = "Var1", direction = "wide")
dat1 <- df.r
dat1[] <- lapply(dat1[], function(x){
  # Check if the column is numeric
  if (is.numeric(x)){
    return(x/sum(x)*100)
  } else{
    return(x)
  }
})
dat1
write.csv(dat1, paste(output_path,"proportionofCelltypesin4pops.csv"))

### for new main cell types 

df.r <- reshape(df.3, idvar = "Var2", timevar = "Var1", direction = "wide")
Error in reshape(df.3, idvar = "Var2", timevar = "Var1", direction = "wide") : 
  object 'df.3' not found

UMAP with original idents to show overlap (or lack there of) Figure 6C

# Figure 6 C
# UMAP with the 4 orig.idents

sample.order <- c("Astrocytes","RadialGlia","Neurons1","Neurons2")
sample.order <- rev(sample.order)

# colour order to match cell type order
clust.colours <- c("royalblue", "indianred2","palegreen2","springgreen4")
 
Idents(seu.sc) <- 'orig.ident'
      
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE)

output_path <- "/Users/rhalenathomas/Documents/Projects_Papers/PhenoID/ForFigures/scRNA/"

### Figure 6C

pdf(paste(output_path,"UMAPscRNAseqMerge4Oct16.pdf"),width = 7, height = 4)
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, label.size = 6) +
  theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16), 
        axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
        axis.text.x = element_text(size =16))
dev.off()
quartz_off_screen 
                2 

## Figure S23 panel 

cell.order <- c("Astrocytes","Endothelial","Glia","NPC","Neurons","Other","Radial Glia")
cell.order <- rev(cell.order)

# colour order to match cell type order
clust.colours <- c("chocolate1","deepskyblue","steelblue4","red2","mediumpurple3","burlywood3", 
                   "pink2")

 
Idents(seu.sc) <- 'Cell_Types'
      
# designated the order of the splits factor
seu.sc$orig.ident <- factor(x = seu.sc$orig.ident, levels = c("Astrocytes","RadialGlia","Neurons1","Neurons2"))


DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, split.by = 'orig.ident', ncol = 2)




pdf(paste(output_path,"UMAP_merge_splitbyorigidentOct16.pdf"),width = 12, height = 7.5)
DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, split.by = 'orig.ident', label.size = 6, ncol = 2) +
  theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16), 
        axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
        axis.text.x = element_text(size =16))
dev.off()
quartz_off_screen 
                2 

# also plot one not split to see the whole thing


#pdf(paste(output_path,"UMAP_merge_CellTypesOct16.pdf"),width = 6.7, height = 4.1)
DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, label.size = 6) +
  theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16), 
        axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
        axis.text.x = element_text(size =16))

#dev.off()

Figure 6D - UMAP with subgroups

pdf(paste(output_path,"UMAP_CellSubtypeMarkersLablesOct16.pdf"),width = 12, height = 5)
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.25, label = TRUE, repel = TRUE)
dev.off()
null device 
          1 

Make a heatmap

Heatmap or Dotplot Save pdf

save the heatmap Change the colours

pdf(paste(output_path,"HeatMapsubtypesOct17.pdf",sep = ""),width = 11, height = 5)
DoHeatmap(seu.sc, features = feature_list, group.by = 'Cell_Subtype_Markers', group.colors = clust.colours, disp.max = 2, disp.min = -1.5,
          angle = 90) + scale_fill_gradientn(colors = c("#154c79", "#eeeee4", "#e28743")) + 
  theme(axis.text.y = element_text(size = 16))
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the
existing scale.
dev.off()
null device 
          1 

Subtype markers

Idents(seu.sc) <- 'Cell_Subtypes'
neurons <- subset(seu.sc, idents = c("Neurons1","Neurons2","Neurons3","Neurons4",
                                     "Neurons5","Neurons6","Neurons7"))

Idents(neurons) <- 'Cell_Subtype_Markers'

pdf(paste(output_path,"UMAP_NeuronsOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(neurons) +  theme(text = element_text(size=16, colour = "black"))
dev.off()
null device 
          1 
Idents(seu.sc) <- 'Cell_Subtypes'
neurons.da <- subset(seu.sc, idents = c("DANeurons1","DANeurons2","DANeurons3"))

Idents(neurons.da) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_DANeuronsOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(neurons.da)+  theme(text = element_text(size=16, colour = "black"))
dev.off()
null device 
          1 
Idents(seu.sc) <- 'Cell_Subtypes'
astro <- subset(seu.sc, idents = c("Astrocytes1","Astrocytes2","Astrocytes3"))
Idents(astro) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_AstroOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(astro)+  theme(text = element_text(size=16, colour = "black"))
dev.off()
null device 
          1 
Idents(seu.sc) <- 'Cell_Subtypes'
rg <- subset(seu.sc, idents = c("RadialGlia1","RadialGlia2","RadialGlia3","RadialGlia4",
                                "RadialGlia5","RadialGlia6"))
Idents(rg) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_RGOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(rg)+  theme(text = element_text(size=16, colour = "black"))
dev.off()
null device 
          1 

DotPlots of markers in cell type subsets


n.markers <- c("ASCL1","CP","GRIA2","MGP","SPARCL1","TPH1","TFPI2","CD24")

pdf(paste(output_path,"Dotplot_NeuSubMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(neurons, features = n.markers) + 
  theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
dev.off()
null device 
          1 
da.markers <- c("RAB3B","TPBG","TTR","TH","SOX6","CALB1","SLC17A6")

pdf(paste(output_path,"Dotplot_DANeuSubMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(neurons.da, features = da.markers) + 
  theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
null device 
          1 
rg.markers <- c("CYP1B1","NEAT1","PTN","RPL41","TOP2A","VCAN","SOX2","SLIT2","HES1","VIM")

pdf(paste(output_path,"Dotplot_RGMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(rg, features = rg.markers) + 
  theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
dev.off()
null device 
          1 
# Apoe, Gfap, Aqp4 and Slc1a3
astro.markers <- c("COL3A1","FABP5","HPD","APOE","S100B","IGFBP2","DBI",
                   "PRSS56", "IGTP","LFIT3","LIGP1",
                   "COL1A2")

pdf(paste(output_path,"Dotplot_AstroMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(astro, features = astro.markers) + 
  theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
Warning in FetchData.Seurat(object = object, vars = features, cells = cells) :
  The following requested variables were not found: IGTP, LFIT3, LIGP1
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
null device 
          1 

Make a label level of main cell types from the merge data


unique(seu.sc$Cell_Subtype_Markers)
 [1] Neurons-GRIA2     NPC               Neurons-SPARCL1   DANeurons-TPBG    Neurons-CP       
 [6] DANeurons-RAB3B   DANeurons-TTR     RadialGlia-CY1B1  RadialGlia-RPL41  RadialGlia-PTN   
[11] Astrocytes-FABP5  Astrocytes-HPD    RadialGlia-TOP2A  Mix               Neurons-TPH1     
[16] Neurons-TFPI1     Neurons-ASCL1     RadialGlia-NEAT1  RadialGlia-VCAN   Neurons-MGP      
[21] Astrocytes-COL3A1
21 Levels: Astrocytes-HPD Neurons-ASCL1 RadialGlia-RPL41 Neurons-SPARCL1 ... RadialGlia-VCAN
Idents(seu.sc) <- 'Cell_Subtype_Markers'

cluster.ids <- c("Astrocytes","Neurons","RadialGlia","Neurons",
                 "Astrocytes","Neurons","RadialGlia","Neurons",
                 "Astrocytes","Neurons","RadialGlia",
                 "DANeurons","Neurons","Mix","NPC",
                 "Neurons","DANeurons","DANeurons",
                 "RadialGlia","RadialGlia","RadialGlia"
                 )


names(cluster.ids) <- levels(seu.sc)
seu.sc <- RenameIdents(seu.sc, cluster.ids)
seu.sc$Cell_Type2 <- Idents(seu.sc)
Idents(seu.sc) <- 'Cell_Type2'
DimPlot(seu.sc)


DimPlot(seu.sc, group.by = 'Cell_Subtype_Markers')

DimPlot(seu.sc, group.by = 'Cell_Subtypes')

DimPlot(seu.sc, group.by = 'Cell_Type2')

NA
NA

# original clusters proportion of cell types in 
library(reshape2)

pr.celltypes <- as.data.frame(table(seu.sc$orig.ident,seu.sc$Cell_Type2))
pr.celltypes <- reshape(pr.celltypes, idvar = "Var2", timevar = "Var1", direction = "wide")
pr.celltypes

table(seu.sc$Cell_Type2)

Astrocytes    Neurons RadialGlia  DANeurons        Mix        NPC 
      3082       2870       1913        476        228        154 
write.csv(pr.celltypes, paste(output_path,"FreqCellTypes2inFACS.csv"))

Proportion of cell types in original FACS populations

pr
                     1          22         43           64          
Var2                 "Neurons2" "Neurons1" "Astrocytes" "RadialGlia"
Freq.DANeurons-RAB3B "131"      " 76"      "  0"        " 52"       
Freq.DANeurons-TPBG  "10"       "50"       " 7"         "46"        
Freq.DANeurons-TTR   "65"       "20"       " 0"         "19"        

Proportion of cell types tests


library("scProportionTest")

prop_test <- sc_utils(seu.sc)

prop_test <- permutation_test(
    prop_test, cluster_identity = "Cell_Type2",
    sample_1 = "Neurons1", sample_2 = "Neurons2",
    sample_identity = "orig.ident"
)


permutation_plot(prop_test)


prop_test <- permutation_test(
    prop_test, cluster_identity = "Cell_Type2",
    sample_1 = "Neurons1", sample_2 = "RadialGlia",
    sample_identity = "orig.ident"
)
permutation_plot(prop_test)



prop_test <- permutation_test(
    prop_test, cluster_identity = "Cell_Type2",
    sample_1 = "Neurons2", sample_2 = "RadialGlia",
    sample_identity = "orig.ident"
)
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
permutation_plot(prop_test)



prop_test <- permutation_test(
    prop_test, cluster_identity = "Cell_Type2",
    sample_1 = "Astrocytes", sample_2 = "RadialGlia",
    sample_identity = "orig.ident"
)
permutation_plot(prop_test)

Check the proportions of subtypes of DA neurons


#library("scProportionTest")

prop_test <- sc_utils(neurons.da)

prop_test <- permutation_test(
    prop_test, cluster_identity = "Cell_Subtype_Markers",
    sample_1 = "Neurons1", sample_2 = "Neurons2",
    sample_identity = "orig.ident"
)


permutation_plot(prop_test)

Differential gene expression between Neurons1 and Neurons2 for Other neurons and DA neurons.

down <- rownames(deg.neurons %>% filter(avg_log2FC < -6))
length(down)
[1] 8

In DA neurons

DotPlot(sub.neur, group.by = 'orig.ident', features = up.down) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results

Look at the GO and other pathway analysis for the DGE

For DA neurons

pdf(paste(output_path,"GOresultesNeurons1vs2.pdf"), width = 12, height = 6)
plotEnrich(t.GObio.da1, showTerms = 10, numChar = 40, y = "Count", orderBy = "Combined.Score") +
  theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da1, showTerms = 10, numChar = 40, y = "Count", orderBy = "Overlap")+
  theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da2, showTerms = 10, numChar = 40, y = "Count", orderBy = "Combined.Score")+
  theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da2, showTerms = 10, numChar = 40, y = "Count", orderBy = "Overlap")+
  theme(text = element_text(size=16, colour = "black"))
dev.off()
null device 
          1 

Dot plots of some up regulated genes

DotPlot(all.neurons, group.by = 'orig.ident', features = regulate.genes) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results
pdf(paste(output_path,"DotPlotDEG_N1vsN2.pdf"))
DotPlot(all.neurons, group.by = 'orig.ident', features = regulate.genes) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
quartz_off_screen 
                2 

BiocManager::install("clusterProfiler")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details

replacement repositories:
    CRAN: https://cran.rstudio.com/

Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Installing package(s) 'clusterProfiler'
also installing the dependencies ‘blob’, ‘plogr’, ‘Biostrings’, ‘fastmatch’, ‘ggfun’, ‘ggplotify’, ‘tidytree’, ‘treeio’, ‘DBI’, ‘RSQLite’, ‘KEGGREST’, ‘DO.db’, ‘fgsea’, ‘aplot’, ‘scatterpie’, ‘shadowtext’, ‘ggtree’, ‘AnnotationDbi’, ‘downloader’, ‘DOSE’, ‘enrichplot’, ‘GO.db’, ‘GOSemSim’, ‘qvalue’, ‘yulab.utils’

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/blob_1.2.3.tgz'
Content type 'application/x-gzip' length 46035 bytes (44 KB)
==================================================
downloaded 44 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/plogr_0.2.0.tgz'
Content type 'application/x-gzip' length 13193 bytes (12 KB)
==================================================
downloaded 12 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/Biostrings_2.64.1.tgz'
Content type 'application/x-gzip' length 14356457 bytes (13.7 MB)
==================================================
downloaded 13.7 MB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/fastmatch_1.1-3.tgz'
Content type 'application/x-gzip' length 49267 bytes (48 KB)
==================================================
downloaded 48 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/ggfun_0.0.7.tgz'
Content type 'application/x-gzip' length 193540 bytes (189 KB)
==================================================
downloaded 189 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/ggplotify_0.1.0.tgz'
Content type 'application/x-gzip' length 137271 bytes (134 KB)
==================================================
downloaded 134 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/tidytree_0.4.1.tgz'
Content type 'application/x-gzip' length 249644 bytes (243 KB)
==================================================
downloaded 243 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/treeio_1.20.2.tgz'
Content type 'application/x-gzip' length 916609 bytes (895 KB)
==================================================
downloaded 895 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/DBI_1.1.3.tgz'
Content type 'application/x-gzip' length 745805 bytes (728 KB)
==================================================
downloaded 728 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/RSQLite_2.2.18.tgz'
Content type 'application/x-gzip' length 4509316 bytes (4.3 MB)
==================================================
downloaded 4.3 MB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/KEGGREST_1.36.3.tgz'
Content type 'application/x-gzip' length 185051 bytes (180 KB)
==================================================
downloaded 180 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/fgsea_1.22.0.tgz'
Content type 'application/x-gzip' length 1489172 bytes (1.4 MB)
==================================================
downloaded 1.4 MB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/aplot_0.1.8.tgz'
Content type 'application/x-gzip' length 56478 bytes (55 KB)
==================================================
downloaded 55 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/scatterpie_0.1.8.tgz'
Content type 'application/x-gzip' length 404495 bytes (395 KB)
==================================================
downloaded 395 KB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/shadowtext_0.1.2.tgz'
Content type 'application/x-gzip' length 226478 bytes (221 KB)
==================================================
downloaded 221 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/ggtree_3.4.4.tgz'
Content type 'application/x-gzip' length 916106 bytes (894 KB)
==================================================
downloaded 894 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/AnnotationDbi_1.58.0.tgz'
Content type 'application/x-gzip' length 5175190 bytes (4.9 MB)
==================================================
downloaded 4.9 MB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/downloader_0.4.tgz'
Content type 'application/x-gzip' length 21727 bytes (21 KB)
==================================================
downloaded 21 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/DOSE_3.22.1.tgz'
Content type 'application/x-gzip' length 6704314 bytes (6.4 MB)
==================================================
downloaded 6.4 MB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/enrichplot_1.16.2.tgz'
Content type 'application/x-gzip' length 283459 bytes (276 KB)
==================================================
downloaded 276 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/GOSemSim_2.22.0.tgz'
Content type 'application/x-gzip' length 920638 bytes (899 KB)
==================================================
downloaded 899 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/qvalue_2.28.0.tgz'
Content type 'application/x-gzip' length 2801783 bytes (2.7 MB)
==================================================
downloaded 2.7 MB

trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/yulab.utils_0.0.5.tgz'
Content type 'application/x-gzip' length 33694 bytes (32 KB)
==================================================
downloaded 32 KB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/clusterProfiler_4.4.4.tgz'
Content type 'application/x-gzip' length 821345 bytes (802 KB)
==================================================
downloaded 802 KB

The downloaded binary packages are in
    /var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T//RtmpOFXQrS/downloaded_packages
installing the source packages ‘DO.db’, ‘GO.db’

trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/DO.db_2.9.tar.gz'
Content type 'application/x-gzip' length 1769978 bytes (1.7 MB)
==================================================
downloaded 1.7 MB

trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/GO.db_3.15.0.tar.gz'
Content type 'application/x-gzip' length 29908485 bytes (28.5 MB)
==================================================
downloaded 28.5 MB

* installing *source* package ‘DO.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (DO.db)
* installing *source* package ‘GO.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (GO.db)

The downloaded source packages are in
    ‘/private/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T/RtmpOFXQrS/downloaded_packages’
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
  'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
  'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
  'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
  'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
  'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
  'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]: 
n
BiocManager::install("pathview")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details

replacement repositories:
    CRAN: https://cran.rstudio.com/

Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Installing package(s) 'pathview'
also installing the dependencies ‘KEGGgraph’, ‘org.Hs.eg.db’

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/KEGGgraph_1.56.0.tgz'
Content type 'application/x-gzip' length 1665739 bytes (1.6 MB)
==================================================
downloaded 1.6 MB

trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/pathview_1.36.1.tgz'
Content type 'application/x-gzip' length 2700402 bytes (2.6 MB)
==================================================
downloaded 2.6 MB

The downloaded binary packages are in
    /var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T//RtmpOFXQrS/downloaded_packages
installing the source package ‘org.Hs.eg.db’

trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/org.Hs.eg.db_3.15.0.tar.gz'
Content type 'application/x-gzip' length 83788492 bytes (79.9 MB)
==================================================
downloaded 79.9 MB

* installing *source* package ‘org.Hs.eg.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (org.Hs.eg.db)

The downloaded source packages are in
    ‘/private/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T/RtmpOFXQrS/downloaded_packages’
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
  'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
  'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
  'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
  'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
  'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
  'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]: 
n
BiocManager::install("enrichplot")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details

replacement repositories:
    CRAN: https://cran.rstudio.com/

Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Warning: package(s) not installed when version(s) same as current; use `force = TRUE` to re-install:
  'enrichplot'
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
  'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
  'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
  'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
  'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
  'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
  'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]: 
n
library(clusterProfiler)

clusterProfiler v4.4.4  For help: https://yulab-smu.top/biomedical-knowledge-mining-book/

If you use clusterProfiler in published research, please cite:
T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu. clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021, 2(3):100141

Attaching package: ‘clusterProfiler’

The following object is masked from ‘package:reshape’:

    rename

The following object is masked from ‘package:stats’:

    filter
library(enrichplot)
# we use ggplot2 to add x axis labels (ex: ridgeplot)
library(ggplot2)

Try with cluster profiler

emapplot(gse, showCategory = 10)
Error in has_pairsim(x) : 
  Term similarity matrix not available. Please use pairwise_termsim function to deal with the results of enrichment analysis.

Predict cell types again to make table 12 Organoids in house data

seu.r <- AIW120
colnames(seu.r@meta.data)
 [1] "orig.ident"                         "nCount_RNA"                        
 [3] "nFeature_RNA"                       "percent.mt"                        
 [5] "predicted.id"                       "prediction.score.RGa"              
 [7] "prediction.score.Astrocytes.2"      "prediction.score.Neurons.e"        
 [9] "prediction.score.Oligodendrocytes"  "prediction.score.Neurons.DA"       
[11] "prediction.score.Neural.Precursors" "prediction.score.Neurons.i"        
[13] "prediction.score.Neurons"           "prediction.score.Other"            
[15] "prediction.score.Epithelial"        "prediction.score.Astrocytes.1"     
[17] "prediction.score.RGd1"              "prediction.score.RGd2"             
[19] "prediction.score.max"               "pred.165days"                      
[21] "RNA_snn_res.0"                      "RNA_snn_res.0.05"                  
[23] "RNA_snn_res.0.25"                   "RNA_snn_res.0.5"                   
[25] "RNA_snn_res.0.8"                    "seurat_clusters"                   
[27] "RNA_snn_res.0.9"                    "RNA_snn_res.1"                     
[29] "RNA_snn_res.1.2"                    "res08names"                        
[31] "res08names2"                        "res08names.gene2"                  
[33] "main.genotype"                      "res08names.gene3"                  
[35] "res08names3"                       
anchors <- FindTransferAnchors(reference = seu.r, query = seu.q, dims = 1:25)
Performing PCA on the provided reference using 2000 features as input.
Projecting cell embeddings
Finding neighborhoods
Finding anchors
    Found 4595 anchors
Filtering anchors
    Retained 2761 anchors
as(<ngCMatrix>, "dgCMatrix") is deprecated since Matrix 1.5-0; do as(., "dMatrix") instead
print("getting predictions")
[1] "getting predictions"
predictions <- TransferData(anchorset = anchors, refdata = seu.r$res08names2, k.weight = 50)
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Predicting cell labels
seu.q <- AddMetaData(seu.q, predictions$predicted.id, col.name = "prediction")
seu.q <- AddMetaData(seu.q, predictions$prediction.score.max, col.name = "prediction.score.max")


seu.q$AIW120.pred <- ifelse(seu.q$prediction.score.max > 0.8, seu.q$prediction, "none")
DimPlot(seu.q, group.by = 'AIW120.pred')

More predictions Developing brain: Cortex Forebrain

Adult brain: whole brain with subtypes Adult brain midbrain and striatum Adult brain midbrain main cell types Adult brain DA or Astro subtypes

Tables of top predictions

t.lables <- as.data.frame(table(seu.q$Cell_Subtype_Markers,seu.q$devcortex))
t.lables$Freq <- as.double(t.lables$Freq)

top.prediction <-as.data.frame(t.lables  %>% group_by(Var1)  %>% top_n(1, Freq))
top.prediction
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUmVhZCBpbiB0aGUgbGFiZWxsZWQgb2JqZWN0IApSdW4gdGhlIGNvcnJlbGF0aW9uIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgdG90YWwgc2NSTkEgcGVyIEZBQ1MgcG9wIGFuZCB0aGUgQUIgbGV2ZWxzCkNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgY2VsbCB0eXBlcyBmcm9tIHRoZSBvcmdpbmFsIGxhYmVscwpVTUFQIG9mIHRoZSBjZWxsIFBPUFMgbWVyZ2VkClVNQVAgb2YgdGhlIHN1YnR5cGVzIGxhYmVsbGVkCgoKCgpgYGB7cn0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KCdyZXNoYXBlJykKbGlicmFyeSgiZ2dwbG90MiIpCgoKYGBgCgoKUmVhZCBpbiB0aGUgbGFibGVsZWQgb2JqZWN0IHNpbmdsZSBjZWxsIHNlcXVlbmNpbmcKCmBgYHtyfQoKcGF0aHdheSA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUGhlbm9JRC9zY1JOQXNlcVNvcnRlZC9vYmpzLyIKc2V1LnNjIDwtIHJlYWRSRFMocGFzdGUocGF0aHdheSwgIkNvbWJpbmVkTGFiZWxlZE1hcmtlcnMxNDEwMjAyMi5SRFMiKSkKc2F2ZVJEUyhzZXUuc2MscGFzdGUocGF0aHdheSwgIkNvbWJpbmVkTGFiZWxlZE1hcmtlcnMxNDEwMjAyMi5SRFMiKSkKCmBgYAoKClJlYWQgaW4gdGhlIEZsb3cgQ3l0b21ldHJ5IGRhdGEKCmBgYHtyfQpvdXRwdXRfcGF0aCA9ICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9GbG93Q3l0b21ldHJ5L1BoZW5vSUQvQW5hbHlzaXMvUGFwZXJGaWd1cmVzL1Bvc3RTb3J0R2F0aW5nUG9wcy8iCnNldS5mYyA8LSByZWFkUkRTKHBhc3RlKG91dHB1dF9wYXRoLCJqdW5lMTBwb3N0U29ydC5zZXUuUkRTIiwgc2VwID0gIiIpKQp1bmlxdWUoc2V1LmZjJEdhdGVkUG9wKQoKIyBib3RoIG5ldXJvbnMxIGFuZCBuZXVyb25zMiBhcmUgbWl4ZWQgaWUgd2hhdCBJIGxhYmVsbGVkIGJlZm9yZSBzb3J0aW5nIGFzIG5ldXJvbnMxIChDRDI0KysrKSB3YXMgbGFiZWxsZWQgYXMgTmV1cm9uczIgaW4gdGhlIGV4cGVpbWVudAoKYGBgCgpNYXJrZXIgbGlzdAoKYGBge3J9CgptYXJrZXIuYWIgPC0gYygiQ0QyNCIsIkNENTYiLCJDRDI5IiwiQ0QxNSIsIkNEMTg0IiwiQ0QxMzMiLCJDRDcxIiwiQ0Q0NCIsIkdMQVNUIiwiQVFQNCIsIkhlcGFDQU0iLCAiQ0QxNDBhIiwiTzQiKQoKbWFya2VyLmdlbmVzIDwtYygiQ0QyNCIsIk5DQU0xIiwiSVRHQjEiLCJGVVQ0IiwiQ1hDUjQiLCJQUk9NMSIsIlRGUkMiLCJDRDQ0IiwiU0xDMUEzIiwiQVFQNCIsIkhFUEFDQU0iLCAiUERHRlJBIiwiTktYNi0yIikKCmBgYAoKCk1ha2UgdGhlIGV4cHJlc3Npb24gbWF0cml4ZXMKCmBgYHtyfQpJZGVudHMoc2V1LnNjKSA8LSAnb3JpZy5pZGVudCcKRGVmYXVsdEFzc2F5KHNldS5zYykgPC0gJ1JOQScKCiMgdG8gaW5jbHVkZSBhbGwgZ2VuZXMgaW4gc2NhbGUgZGF0YSBhZGQgdGhlIGZlYXR1cmVzIGFyZ3VtZW50CnNldS5zYyA8LSBTY2FsZURhdGEob2JqZWN0ID0gc2V1LnNjLCBmZWF0dXJlcyA9IHJvd25hbWVzKHNldS5zYykpCgoKc2NSTkFzZXEubWVhbiA8LSBhcy5kYXRhLmZyYW1lKEF2ZXJhZ2VFeHByZXNzaW9uKHNldS5zYyxmZWF0dXJlcyA9IG1hcmtlci5nZW5lcywgYXNzYXlzID0gJ1JOQScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAnb3JpZy5pZGVudCcsIHNsb3Q9ICdzY2FsZS5kYXRhJykpCgoKIyBjaGFuZ2UgZ2VuZSBuYW1lcyB0byBwcm90ZWluL0FCIG5hbWVzCnJvd25hbWVzKHNjUk5Bc2VxLm1lYW4pIDwtIG1hcmtlci5hYgoKIyBnZXQgdGhlIG1lYW4gZXhwcmVzc2lvbiBmcm9tIEZBQ1MgCkRlZmF1bHRBc3NheShzZXUuZmMpIDwtICdSTkEnCklkZW50cyhzZXUuZmMpIDwtICdHYXRlZFBvcCcKCiNzZXUuZmMgPC0gU2NhbGVEYXRhKHNldS5mYykKCkZDLm1lYW4gPC0gYXMuZGF0YS5mcmFtZShBdmVyYWdlRXhwcmVzc2lvbihzZXUuZmMsIGFzc2F5cyA9ICdSTkEnLGZlYXR1cmVzID0gbWFya2VyLmFiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gJ0dhdGVkUG9wJywgc2xvdD0gJ3NjYWxlLmRhdGEnKSkKCgpgYGAKCkNhbGN1bGF0ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byBtYXRyaXhlcwoKYGBge3J9CgojIHJlbmFtZSBhbmQgcmVvcmRlciBkYXRhZnJhbWVzIHRvIG1hdGNoCmNvbG5hbWVzKEZDLm1lYW4pCmNvbG5hbWVzKEZDLm1lYW4pIDwtIGMoIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiwiTmV1cm9uczIiLCJOZXVyb25zMSIpCmNvbG5hbWVzKEZDLm1lYW4pCgpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKQpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKSA8LSBjKCJOZXVyb25zMiIsIk5ldXJvbnMxIiwiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiKQpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKQpybmEubWVhbiA8LSBzY1JOQXNlcS5tZWFuICU+JSBzZWxlY3QoIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiwiTmV1cm9uczEiLCJOZXVyb25zMiIpCkZDLm1lYW4gPC0gRkMubWVhbiAlPiUgc2VsZWN0KCJBc3Ryb2N5dGVzIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMxIiwiTmV1cm9uczIiKQoKZGYuY29yIDwtIGNvcihGQy5tZWFuLCBybmEubWVhbikKIyBmaXJzdCBvbmUgaXMgdGhlIHJvd3MgYW5kIHNlY29uZCBpcyB0aGUgY29sdW1ucywgRkMgbWVhc3VyZXMgb24gdGhlIHkgYXhpcwoKZGYuY29yCgoKIyBOZXVyb25zMiBzaG91bGQgYmUgdGhlIGhpZ2ggQ0Q1NiBwb3B1bGF0aW9uIGFuZCBpdCBpcyBpbiBib3RoIGNhc2VzIAojIE5ldXJvbnMxIHNob3VsZCBiZSB0aGUgaGlnaCBDRDI0IGFuZCBpdCBpcwoKRkMubWVhbgpybmEubWVhbgoKIyB0cnkgY2FsY3VsYXRpbmcgeiBzY29yZXMKIyB0aGlzIHdvcmtzIG9uIHJvd3MKZGF0YSA8LSBGQy5tZWFuCmFkZC5yb3duYW1lcyA8LSByb3duYW1lcyhkYXRhKQpGQy5tZWFuLnogPC0gYXMuZGF0YS5mcmFtZShzYXBwbHkoZGF0YSwgZnVuY3Rpb24oZGF0YSkgKGRhdGEtbWVhbihkYXRhKSkvc2QoZGF0YSkpKQoKcm93bmFtZXMoRkMubWVhbi56KSA8LWFkZC5yb3duYW1lcwpGQy5tZWFuLnoKCgpkYXRhIDwtIHJuYS5tZWFuCmFkZC5yb3duYW1lcyA8LSByb3duYW1lcyhkYXRhKQpybmEubWVhbi56IDwtIGFzLmRhdGEuZnJhbWUoc2FwcGx5KGRhdGEsIGZ1bmN0aW9uKGRhdGEpIChkYXRhLW1lYW4oZGF0YSkpL3NkKGRhdGEpKSkKCnJvd25hbWVzKHJuYS5tZWFuLnopIDwtYWRkLnJvd25hbWVzCnJuYS5tZWFuLnoKCgpkZi5jb3IgPC0gY29yKEZDLm1lYW4ueiwgcm5hLm1lYW4ueikKZGYuY29yCgp3cml0ZS5jc3YoZGYuY29yLCBwYXN0ZShvdXRwdXRfcGF0aCwiQ29ycmVsYXRpb25zRkNzY1JOQXNlcS5jc3YiKSkKCgpgYGAKClBsb3QgdGhlIGhlYXRtYXAKRmlndXJlIDZBCgpgYGB7cn0KIyBuZWVkIHRvIG1lbHQgdGhlIG1hdHJpeApsb25nRGF0YTwtIG1lbHQoZGYuY29yKQoKaGVhZChsb25nRGF0YSkKY29sbmFtZXMobG9uZ0RhdGEpIDwtIGMoIkZDIiwic2NSTkEiLCJSMiIpCgpnZ3Bsb3QobG9uZ0RhdGEsIGFlcyh4PXNjUk5BLHk9RkMsIGZpbGwgPVIyKSkgKyBnZW9tX3RpbGUoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gIiMwNzVBRkYiLAogICAgICAgICAgICAgICAgICAgICAgIG1pZCA9ICIjRkZGRkNDIiwKICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gIiNGRjAwMDAiKSArCiAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGxhYmVsID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrcyA9IEZBTFNFKSkgKyB0aGVtZV9idygpICsKICBjb29yZF9maXhlZCgpICArc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQ9YygwLDApKSsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgY29sb3VyID0gImJsYWNrIiwgYW5nbGUgPSA5MCksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9IDE4LCBjb2xvdXIgPSAiYmxhY2siKSkgICsgeGxhYignc2NSTkFzZXEnKSArIHlsYWIoJ0Zsb3cgQ3l0b21ldHJ5JykgCgpvdXRwdXRfcGF0aCA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL1Byb2plY3RzX1BhcGVycy9QaGVub0lEL0ZvckZpZ3VyZXMvc2NSTkEvIgoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJGQ19zY1JOQV9jb3JyZWxhdGlvbk9jdDE2LnBkZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDUpCmdncGxvdChsb25nRGF0YSwgYWVzKHg9c2NSTkEseT1GQywgZmlsbCA9UjIpKSArIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiIzA3NUFGRiIsCiAgICAgICAgICAgICAgICAgICAgICAgbWlkID0gIiNGRkZGQ0MiLAogICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiI0ZGMDAwMCIsIG1pZHBvaW50ID0gMCwgbGltaXQgPSBjKC0wLjUsMC41KSkgKwogICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihsYWJlbCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja3MgPSBGQUxTRSkpICsgdGhlbWVfYncoKSArCiAgY29vcmRfZml4ZWQoKSAgK3NjYWxlX3hfZGlzY3JldGUoZXhwYW5kPWMoMCwwKSkgKwogIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kPWMoMCwwKSkgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgY29sb3VyID0gImJsYWNrIiwgYW5nbGUgPSA5MCksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9IDE2LCBjb2xvdXIgPSAiYmxhY2siKSkgICsgeGxhYignc2NSTkFzZXEnKSArIHlsYWIoJ0Zsb3cgQ3l0b21ldHJ5JykgCgpkZXYub2ZmKCkKCgoKCmBgYAoKQ29tcGFyZSBwcm9wb3J0aW9ucyBvZiBjZWxscyBpbiBlYWNoIEZBQ1MgcG9wIC0gRmlndXJlIDZCCgpgYGB7cn0KCiMgc2F2ZSB0aGUgcHJvcG9ydGlvbiBjaGFydCB3aXRoIGNvbG91cnMgbWF0Y2hpbmcgdGhlIFVNQVBzIApkZiA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5zYyRvcmlnLmlkZW50LCBzZXUuc2MkQ2VsbF9UeXBlcykpCgojIHRoZSBjaGFydCB3aWxsIGRlZmF1bHQgdG8gYWxwaGFiZXRpY2FsCgpjbHVzdC5jb2xvdXJzIDwtIGMoImNob2NvbGF0ZTEiLCJkZWVwc2t5Ymx1ZSIsInN0ZWVsYmx1ZTQiLCJtZWRpdW1wdXJwbGUzIiwicmVkMiIsImJ1cmx5d29vZDMiLCAgICAgInBpbmsyIikKCiMgYnV0IG5vdCBmb3IgdGhlIHggYXhpcyAtIHJlb3JkZXIgd2l0aCBmYWN0b3IgdG8gbWF0Y2ggZmlndXJlIDZBCmRmJEZBQ3BvcCA8LSBmYWN0b3IoZGYkVmFyMSwgbGV2ZWxzID0gYygiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiLCJOZXVyb25zMSIsIk5ldXJvbnMyIikpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkJhckNoYXJ0UHJvcG9ydGlvbkNlbGxUeXBlc2luNHBvcHNPY3QxNi5wZGYiKSwgaGVpZ2h0ID0gNSwgd2lkdGggPSA2KQpnZ3Bsb3QoZGYsIGFlcyh4ID0gRkFDcG9wLCB5ID0gRnJlcSwgZmlsbCA9IFZhcjIpKSArIAogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArIHRoZW1lX2NsYXNzaWMoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2x1c3QuY29sb3VycykgKwogICNzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIG9mIENlbGxzIiwgeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSAKZGV2Lm9mZigpCgpgYGAKCgpNYWtlIGEgdGFibGUgb2YgY2VsbCB0eXBlcwoKYGBge3J9CgpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocmVzaGFwZSkKCiMgZm9yIG9yaWdpbmFsIGNlbGwgdHlwZXMgCgoKZGYuciA8LSByZXNoYXBlKGRmLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpkYXQxIDwtIGRmLnIKZGF0MVtdIDwtIGxhcHBseShkYXQxW10sIGZ1bmN0aW9uKHgpewogICMgQ2hlY2sgaWYgdGhlIGNvbHVtbiBpcyBudW1lcmljCiAgaWYgKGlzLm51bWVyaWMoeCkpewogICAgcmV0dXJuKHgvc3VtKHgpKjEwMCkKICB9IGVsc2V7CiAgICByZXR1cm4oeCkKICB9Cn0pCmRhdDEKd3JpdGUuY3N2KGRhdDEsIHBhc3RlKG91dHB1dF9wYXRoLCJwcm9wb3J0aW9ub2ZDZWxsdHlwZXNpbjRwb3BzLmNzdiIpKQoKCgoKYGBgCgoKClVNQVAgd2l0aCBvcmlnaW5hbCBpZGVudHMgdG8gc2hvdyBvdmVybGFwIChvciBsYWNrIHRoZXJlIG9mKQpGaWd1cmUgNkMKCmBgYHtyfQojIEZpZ3VyZSA2IEMKIyBVTUFQIHdpdGggdGhlIDQgb3JpZy5pZGVudHMKCnNhbXBsZS5vcmRlciA8LSBjKCJBc3Ryb2N5dGVzIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMxIiwiTmV1cm9uczIiKQpzYW1wbGUub3JkZXIgPC0gcmV2KHNhbXBsZS5vcmRlcikKCiMgY29sb3VyIG9yZGVyIHRvIG1hdGNoIGNlbGwgdHlwZSBvcmRlcgpjbHVzdC5jb2xvdXJzIDwtIGMoInJveWFsYmx1ZSIsICJpbmRpYW5yZWQyIiwicGFsZWdyZWVuMiIsInNwcmluZ2dyZWVuNCIpCiAKSWRlbnRzKHNldS5zYykgPC0gJ29yaWcuaWRlbnQnCgpSdW5VTUFQKCkKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSkKCm91dHB1dF9wYXRoIDwtICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvUHJvamVjdHNfUGFwZXJzL1BoZW5vSUQvRm9yRmlndXJlcy9zY1JOQS8iCgojIyMgRmlndXJlIDZDCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBzY1JOQXNlcU1lcmdlNE9jdDE2LnBkZiIpLHdpZHRoID0gNywgaGVpZ2h0ID0gNCkKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSwgbGFiZWwuc2l6ZSA9IDYpICsKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0xNikpCmRldi5vZmYoKQoKCiMjIEZpZ3VyZSBTMjMgcGFuZWwgCgpjZWxsLm9yZGVyIDwtIGMoIkFzdHJvY3l0ZXMiLCJFbmRvdGhlbGlhbCIsIkdsaWEiLCJOUEMiLCJOZXVyb25zIiwiT3RoZXIiLCJSYWRpYWwgR2xpYSIpCmNlbGwub3JkZXIgPC0gcmV2KGNlbGwub3JkZXIpCgojIGNvbG91ciBvcmRlciB0byBtYXRjaCBjZWxsIHR5cGUgb3JkZXIKY2x1c3QuY29sb3VycyA8LSBjKCJjaG9jb2xhdGUxIiwiZGVlcHNreWJsdWUiLCJzdGVlbGJsdWU0IiwicmVkMiIsIm1lZGl1bXB1cnBsZTMiLCJidXJseXdvb2QzIiwgCiAgICAgICAgICAgICAgICAgICAicGluazIiKQoKIApJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9UeXBlcycKICAgICAgCiMgZGVzaWduYXRlZCB0aGUgb3JkZXIgb2YgdGhlIHNwbGl0cyBmYWN0b3IKc2V1LnNjJG9yaWcuaWRlbnQgPC0gZmFjdG9yKHggPSBzZXUuc2Mkb3JpZy5pZGVudCwgbGV2ZWxzID0gYygiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiLCJOZXVyb25zMSIsIk5ldXJvbnMyIikpCgoKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gY2VsbC5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjEsIGxhYmVsID0gRkFMU0UsIHNwbGl0LmJ5ID0gJ29yaWcuaWRlbnQnLCBuY29sID0gMikKCgoKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiVU1BUF9tZXJnZV9zcGxpdGJ5b3JpZ2lkZW50T2N0MTYucGRmIiksd2lkdGggPSAxMiwgaGVpZ2h0ID0gNy41KQpEaW1QbG90KHNldS5zYywgb3JkZXIgPSBjZWxsLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSwgc3BsaXQuYnkgPSAnb3JpZy5pZGVudCcsIGxhYmVsLnNpemUgPSA2LCBuY29sID0gMikgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTYpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSkKZGV2Lm9mZigpCgoKIyBhbHNvIHBsb3Qgb25lIG5vdCBzcGxpdCB0byBzZWUgdGhlIHdob2xlIHRoaW5nCgoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX21lcmdlX0NlbGxUeXBlc09jdDE2LnBkZiIpLHdpZHRoID0gNi43LCBoZWlnaHQgPSA0LjEpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IGNlbGwub3JkZXIsIGNvbHMgPSBjbHVzdC5jb2xvdXJzLCBzaHVmZmxlID0gVFJVRSwgcmFzdGVyPUZBTFNFLCBwdC5zaXplID0gMC4xLCBsYWJlbCA9IEZBTFNFLCBsYWJlbC5zaXplID0gNikgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTYpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSkKZGV2Lm9mZigpCgoKCgoKYGBgCgpGaWd1cmUgNkQgLSBVTUFQIHdpdGggc3ViZ3JvdXBzCgpgYGB7cn0KCnVuaXF1ZShzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMpCiMgMjEgbGV2ZWxzIHdpbGwgbmVlZCAyMSBjb2xvdXJzIAojIE5ldXJvbnMgLSBwdXJwbGVzCiMgREEgbmV1cm9ucyBncmVlbgojIE5QQyByZWQKIyBBc3Ryb2N5dGVzIC0gT3JhbmdlIC0KIyBSYWRpYWwgR2xpYSAtIFBpbmsgeWVsbG93CiMgb3RoZXIgY2VsbHMgYmx1ZXMKCnNhbXBsZS5vcmRlciA8LSBjKCJBc3Ryb2N5dGVzLUNPTDNBMSIsIkFzdHJvY3l0ZXMtRkFCUDUiLCAiQXN0cm9jeXRlcy1IUEQiLAogICAgICAgICAgICAgICAgICAiREFOZXVyb25zLVJBQjNCIiwiREFOZXVyb25zLVRQQkciLCJEQU5ldXJvbnMtVFRSIiwKICAgICAgICAgICAgICAgICAgIk1peCIsIk5QQyIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLUFTQ0wxIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtQ1AiLCJOZXVyb25zLUdSSUEyIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtTUdQIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLVRQSDEiLCAiTmV1cm9ucy1URlBJMSIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLUNZMUIxIiwgIlJhZGlhbEdsaWEtTkVBVDEiLCJSYWRpYWxHbGlhLVBUTiIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLVJQTDQxIiwgIlJhZGlhbEdsaWEtVE9QMkEiLCAiUmFkaWFsR2xpYS1WQ0FOIikKc2FtcGxlLm9yZGVyIDwtIHJldihzYW1wbGUub3JkZXIpCgoKY2x1c3QuY29sb3VycyA8LSBjKCIjRjFDMTY2IiwiI0ZGOTQwMCIsIiNFOTU5MDEiLCAgICAgICAgICAjIG9yYW5nZXMgQXN0cm9jeXRlcwogICAgICAgICAgICAgICAgICAgIiM0M0Q1OUMiLCIjN0RBNjk2IiwiIzE1QUUzNiIsICAgICAjIGdyZWVucyBEQSBuZXVyb25zCiAgICAgICAgICAgICAgICAgICAic3RlZWxibHVlIiwicmVkMiIsICAgIyBtaXggYW5kIE5QQwogICAgICAgICAgICAgICAgICAgIiM4RjY3RkYiLAogICAgICAgICAgICAgICAgICAgIiM2ODQwREIiLCIjOUI4QkM3IiwgICAjIG5ldXJvbnMgMiAgQ1AsIEdSSUEyCiAgICAgICAgICAgICAgICAgICAiIzdCMjJGQiIsICAgICMgTUdQCiAgICAgICAgICAgICAgICAgICAicHVycGxlIiwgIyBTUEFSQ0wxCiAgICAgICAgICAgICAgICAgICAiIzk4NjNFNSIsIiM4RTM2RDIiLCAjIFRQSDEsIFRGUEkxCiAgICAgICAgICAgICAgICAgICAiI0Y2OEQ4RCIsICMgUkcgQ1kxQjEKICAgICAgICAgICAgICAgICAgICIjRjY4ODg4IiwiI0Y2ODhCRCIsICAgIyBSRyBORUFUMSwgUFROIAogICAgICAgICAgICAgICAgICAgIiNGNTI4OEEiLCIjREM1N0NGIiwiI0YzQTZFQyIpCgojRGltUGxvdChzZXUuc2MsIHB0LnNpemUgPSAwLjEsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJyAKCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUpCgpEaW1QbG90KHNldS5zYywgb3JkZXIgPSBzYW1wbGUub3JkZXIsIGNvbHMgPSBjbHVzdC5jb2xvdXJzLCBzaHVmZmxlID0gVFJVRSwgcmFzdGVyPUZBTFNFLCBwdC5zaXplID0gMC4yNSwgbGFiZWwgPSBGQUxTRSkKCgoKI0lkZW50cyhzZXUuc2MpIDwtICdDZWxsX1N1YnR5cGVzJwojRGltUGxvdChzZXUuc2MsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUpCgoKIyBzYXZlIEZpZ3VyZSA2RAojcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX0NlbGxTdWJ0eXBlTWFya2Vyc09jdDE2LnBkZiIpLHdpZHRoID0gOS40LCBoZWlnaHQgPSAzLjkpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IEZBTFNFKQojZGV2Lm9mZigpCgoKIyBGaWd1cmUgUzI1CiMgd2l0aCBsYWJlbHMKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX0NlbGxTdWJ0eXBlTWFya2Vyc0xhYmxlc09jdDE2LnBkZiIpLHdpZHRoID0gMTIsIGhlaWdodCA9IDUpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVFJVRSkKZGV2Lm9mZigpCgoKCmBgYAoKCk1ha2UgYSBoZWF0bWFwCgpgYGB7cn0KCiMgc29tZSBEQSBjbGFzc2ljIG1hcmtlcgojIHNvbWUgbmV1cm9uYWwgbWFya2VycwojIHNvbWUgClBEX3BvdWxpbiA9IGMoIlRIIiwiU0xDNkEzIiwiU0xDMThBMiIsIlNPWDYiLCJORE5GIiwiU05DRyIsIkFMREgxQTEiLCJDQUxCMSIsIlRBQ1IyIiwiU0xDMTdBNiIsIlNMQzMyQTEiLCJPVFgyIiwiR1JQIiwiTFBMIiwiQ0NLIiwiVklQIikKCiNsaWtlbHkgdG9vIG1hbnkKZnQgPC0gYygiQ09MM0ExIiwiRkFCUDUiLCJIUEQiLCJSQUIzQiIsIlRQQkciLCJUVFIiLCJTT1gyIiwiQVNDTDEiLCJDUCIsIkdSSUEyIiwKICAgICAgICAiTUdQIiwiU1BBUkNMMSIsIlRQSDEiLCJURlBJMSIsIkNZMUIxIiwiTkVBVDEiLCJQVE4iLCJSUEw0MSIsIlRPUDJBIiwiVkNBTiIpCgojIHRvIGNoYW5nZSB0aGUgY2VsbCB0eXBlIG9yZGVyCklkZW50cyhzZXUuc2MpIDwtICdDZWxsX1N1YnR5cGVfTWFya2VycycKCgoKc2V1LnNjJENlbGxfU3VidHlwZV9NYXJrZXJzIDwtIGZhY3RvcihzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsIGxldmVscyA9IHNhbXBsZS5vcmRlcikKCiNzZXUuc2MgPC0gU2NhbGVEYXRhKHNldS5zYykKI0RvSGVhdG1hcChzZXUuc2MsIGZlYXR1cmVzID0gUERfcG91bGluLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycsIHNsb3QgPSAnc2NhbGUuZGF0YScpCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZ0LCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCiMgdGhlc2UgYXJlIG5vdCB2ZXJ5IGhlbHBmdWwgbWFya2VycyAKIyBuZWVkIHRvIHJldmVyc2Ugc2FtcGxlIG9yZGVyIGZvciBoZWF0bWFwcwpEb0hlYXRtYXAoc2V1LnNjLCBmZWF0dXJlcyA9IGZ0LCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpCgpmdCA9IGMoKQoKZmVhdHVyZV9saXN0ID0gYygiUEFYNiIsIk9UWDIiLCJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIsIk1BUDIiLAogICAgICAgICAgICAgICAgICJOQ0FNMSIsIkNEMjQiLCJHUklBMiIsIkdBQkJSMSIpCgpmZWF0dXJlX2xpc3QgPSBjKCJUSCIsIlBBWDYiLCJPVFgyIiwiTUFQMiIsIk5DQU0xIiwiQ0QyNCIsIkdSSUEyIiwiR0FCQlIxIiwKICAgICAgICAgICAgICAgICAiVklNIiwiU0xDMUEzIiwiU09YMiIsIkhFUzEiLCJORVMiLCJTMTAwQiIsIlNPWDkiLCJHRkFQIgogICAgICAgICAgICAgICAgICkKCiJHUklBMiIsIkdBQkJSMSIKCmZlYXR1cmVfbGlzdCA9IGMoIk1BUDIiLCJOQ0FNMSIsIkNEMjQiLCJHUklBMiIpCgpmZWF0dXJlX2xpc3QgPSBjKCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHUklOMkIiLCwiR0FEMSIsIkdBRDIiLCJHQUJSQTEiLCJHQUJSQjIiLCJUSCIsIkFMREgxQTEiLCJMTVgxQiIsIk5SNEEyIiwiQ09SSU4iLCJDQUxCMSIsIktDTko2IiwiQ1hDUjQiLCJJVEdBNiIsIlNMQzFBMyIsIkNENDQiLCJBUVA0IiwiUzEwMEIiLCAiUERHRlJBIiwiT0xJRzIiLCJNQlAiLCJDTEROMTEiLCJWQ0FNMSIpCgoiU09YOSIKZmVhdHVyZV9saXN0IDwtIGMoIlJCRk9YMyIsIkdSSU4yQiIsIkdBRDEiLCJHQUQyIiwiR0FCUkExIiwiR0FCUkIyIiwiVEgiKQoKZmVhdHVyZV9saXN0IDwtIGMoIlNMQzFBMyIsICJQQVg2IiwgIlNPWDIiLCAiUERHRkQiLCAiR0xJMyIsICJTVE1OMiIsICJORVVST0Q2IiwgIlZJTSIsICJIRVMxIikKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdCwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgojIHRoZXNlIGFyZSBub3QgdmVyeSBoZWxwZnVsIG1hcmtlcnMgCiMgbmVlZCB0byByZXZlcnNlIHNhbXBsZSBvcmRlciBmb3IgaGVhdG1hcHMKRG9IZWF0bWFwKHNldS5zYywgZmVhdHVyZXMgPSBmZWF0dXJlX2xpc3QsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKCgoKCmBgYAoKSGVhdG1hcCBvciBEb3RwbG90IApTYXZlIHBkZgoKCmBgYHtyfQoKCmZlYXR1cmVfbGlzdCA9IGMoIlRIIiwiUEFYNiIsIk9UWDIiLCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLAogICAgICAgICAgICAgICAgICJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIKICAgICAgICAgICAgICAgICApCgpmZWF0dXJlX2xpc3QuZCA9IGMoIlBBWDYiLCJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIk9UWDIiLAogICAgICAgICAgICAgICAgICJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLCJTMTAwQiIsIlNPWDkiCiAgICAgICAgICAgICAgICAgKQoKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdC5kLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9ICJUSCIsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQojIHRoZXNlIGFyZSBub3QgdmVyeSBoZWxwZnVsIG1hcmtlcnMgCiMgbmVlZCB0byByZXZlcnNlIHNhbXBsZSBvcmRlciBmb3IgaGVhdG1hcHMKCnNhbXBsZS5vcmRlci5yIDwtIHJldihzYW1wbGUub3JkZXIpCgpzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMgPC0gZmFjdG9yKHNldS5zYyRDZWxsX1N1YnR5cGVfTWFya2VycywgbGV2ZWxzID0gc2FtcGxlLm9yZGVyLnIpCgoKIyBzYXZlIHRoZSBkb3RwbG90cwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdFBsb3RDZWxsU3VidHlwZXNPY3QxNy5wZGYiKSkKRG90UGxvdChzZXUuc2MsIGZlYXR1cmVzID0gZmVhdHVyZV9saXN0LmQsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpkZXYub2ZmKCkKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90UGxvdFRIYnlzdWJ0eXBlc09jdDE3LnBkZiIpKQpEb3RQbG90KHNldS5zYywgZmVhdHVyZXMgPSAiVEgiLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgpgYGAKCnNhdmUgdGhlIGhlYXRtYXAKQ2hhbmdlIHRoZSBjb2xvdXJzCgpgYGB7cn0KCmZlYXR1cmVfbGlzdCA9IGMoIlRIIiwiUEFYNiIsIk9UWDIiLCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLAogICAgICAgICAgICAgICAgICJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIKICAgICAgICAgICAgICAgICApCgojIHJldmVyc2UgdGhlIGNlbGwgdHlwZSBvcmRlcgpzYW1wbGUub3JkZXIuciA8LSByZXYoc2FtcGxlLm9yZGVyKQoKc2V1LnNjJENlbGxfU3VidHlwZV9NYXJrZXJzIDwtIGZhY3RvcihzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsIGxldmVscyA9IHNhbXBsZS5vcmRlci5yKQoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJIZWF0TWFwc3VidHlwZXNPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDExLCBoZWlnaHQgPSA1KQpEb0hlYXRtYXAoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdCwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnLCBncm91cC5jb2xvcnMgPSBjbHVzdC5jb2xvdXJzLCBkaXNwLm1heCA9IDIsIGRpc3AubWluID0gLTEuNSwKICAgICAgICAgIGFuZ2xlID0gOTApICsgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiIzE1NGM3OSIsICIjZWVlZWU0IiwgIiNlMjg3NDMiKSkgKyAKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKQpkZXYub2ZmKCkKCgpgYGAKCgpTdWJ0eXBlIG1hcmtlcnMKCgpgYGB7cn0KSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZXMnCm5ldXJvbnMgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiTmV1cm9uczEiLCJOZXVyb25zMiIsIk5ldXJvbnMzIiwiTmV1cm9uczQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvbnM1IiwiTmV1cm9uczYiLCJOZXVyb25zNyIpKQoKSWRlbnRzKG5ldXJvbnMpIDwtICdDZWxsX1N1YnR5cGVfTWFya2VycycKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiVU1BUF9OZXVyb25zT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEaW1QbG90KG5ldXJvbnMpICsgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCmRldi5vZmYoKQoKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZXMnCm5ldXJvbnMuZGEgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiREFOZXVyb25zMSIsIkRBTmV1cm9uczIiLCJEQU5ldXJvbnMzIikpCgpJZGVudHMobmV1cm9ucy5kYSkgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfREFOZXVyb25zT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEaW1QbG90KG5ldXJvbnMuZGEpKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9TdWJ0eXBlcycKYXN0cm8gPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiQXN0cm9jeXRlczEiLCJBc3Ryb2N5dGVzMiIsIkFzdHJvY3l0ZXMzIikpCklkZW50cyhhc3RybykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfQXN0cm9PY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRpbVBsb3QoYXN0cm8pKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9TdWJ0eXBlcycKcmcgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiUmFkaWFsR2xpYTEiLCJSYWRpYWxHbGlhMiIsIlJhZGlhbEdsaWEzIiwiUmFkaWFsR2xpYTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhNSIsIlJhZGlhbEdsaWE2IikpCklkZW50cyhyZykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfUkdPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRpbVBsb3QocmcpKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgoKCgpgYGAKCgpEb3RQbG90cyBvZiBtYXJrZXJzIGluIGNlbGwgdHlwZSBzdWJzZXRzCgpgYGB7cn0KCm4ubWFya2VycyA8LSBjKCJBU0NMMSIsIkNQIiwiR1JJQTIiLCJNR1AiLCJTUEFSQ0wxIiwiVFBIMSIsIlRGUEkyIiwiQ0QyNCIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfTmV1U3ViTWFya2Vyc09jdDE3LnBkZiIsc2VwID0gIiIpLHdpZHRoID0gNywgaGVpZ2h0ID0gNCkKRG90UGxvdChuZXVyb25zLCBmZWF0dXJlcyA9IG4ubWFya2VycykgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpkZXYub2ZmKCkKCmRhLm1hcmtlcnMgPC0gYygiUkFCM0IiLCJUUEJHIiwiVFRSIiwiVEgiLCJTT1g2IiwiQ0FMQjEiLCJTTEMxN0E2IikKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90cGxvdF9EQU5ldVN1Yk1hcmtlcnNPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRvdFBsb3QobmV1cm9ucy5kYSwgZmVhdHVyZXMgPSBkYS5tYXJrZXJzKSArIAogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIiksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCmRldi5vZmYoKQoKcmcubWFya2VycyA8LSBjKCJDWVAxQjEiLCJORUFUMSIsIlBUTiIsIlJQTDQxIiwiVE9QMkEiLCJWQ0FOIiwiU09YMiIsIlNMSVQyIiwiSEVTMSIsIlZJTSIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfUkdNYXJrZXJzT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEb3RQbG90KHJnLCBmZWF0dXJlcyA9IHJnLm1hcmtlcnMpICsgCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgojIEFwb2UsIEdmYXAsIEFxcDQgYW5kIFNsYzFhMwphc3Ryby5tYXJrZXJzIDwtIGMoIkNPTDNBMSIsIkZBQlA1IiwiSFBEIiwiQVBPRSIsIlMxMDBCIiwiSUdGQlAyIiwiREJJIiwKICAgICAgICAgICAgICAgICAgICJQUlNTNTYiLCAiSUdUUCIsIkxGSVQzIiwiTElHUDEiLAogICAgICAgICAgICAgICAgICAgIkNPTDFBMiIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfQXN0cm9NYXJrZXJzT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEb3RQbG90KGFzdHJvLCBmZWF0dXJlcyA9IGFzdHJvLm1hcmtlcnMpICsgCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgoKYGBgCgpNYWtlIGEgbGFiZWwgbGV2ZWwgb2YgbWFpbiBjZWxsIHR5cGVzIGZyb20gdGhlIG1lcmdlIGRhdGEKCmBgYHtyfQoKdW5pcXVlKHNldS5zYyRDZWxsX1N1YnR5cGVfTWFya2VycykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwoKY2x1c3Rlci5pZHMgPC0gYygiQXN0cm9jeXRlcyIsIk5ldXJvbnMiLCJSYWRpYWxHbGlhIiwiTmV1cm9ucyIsCiAgICAgICAgICAgICAgICAgIkFzdHJvY3l0ZXMiLCJOZXVyb25zIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMiLAogICAgICAgICAgICAgICAgICJBc3Ryb2N5dGVzIiwiTmV1cm9ucyIsIlJhZGlhbEdsaWEiLAogICAgICAgICAgICAgICAgICJEQU5ldXJvbnMiLCJOZXVyb25zIiwiTWl4IiwiTlBDIiwKICAgICAgICAgICAgICAgICAiTmV1cm9ucyIsIkRBTmV1cm9ucyIsIkRBTmV1cm9ucyIsCiAgICAgICAgICAgICAgICAgIlJhZGlhbEdsaWEiLCJSYWRpYWxHbGlhIiwiUmFkaWFsR2xpYSIKICAgICAgICAgICAgICAgICApCgoKbmFtZXMoY2x1c3Rlci5pZHMpIDwtIGxldmVscyhzZXUuc2MpCnNldS5zYyA8LSBSZW5hbWVJZGVudHMoc2V1LnNjLCBjbHVzdGVyLmlkcykKc2V1LnNjJENlbGxfVHlwZTIgPC0gSWRlbnRzKHNldS5zYykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfVHlwZTInCkRpbVBsb3Qoc2V1LnNjKQoKRGltUGxvdChzZXUuc2MsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKRGltUGxvdChzZXUuc2MsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZXMnKQpEaW1QbG90KHNldS5zYywgZ3JvdXAuYnkgPSAnQ2VsbF9UeXBlMicpCgoKYGBgCgoKYGBge3J9CgojIG9yaWdpbmFsIGNsdXN0ZXJzIHByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiAKbGlicmFyeShyZXNoYXBlMikKCnByLmNlbGx0eXBlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5zYyRvcmlnLmlkZW50LHNldS5zYyRDZWxsX1R5cGUyKSkKcHIuY2VsbHR5cGVzIDwtIHJlc2hhcGUocHIuY2VsbHR5cGVzLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpwci5jZWxsdHlwZXMKCnRhYmxlKHNldS5zYyRDZWxsX1R5cGUyKQoKd3JpdGUuY3N2KHByLmNlbGx0eXBlcywgcGFzdGUob3V0cHV0X3BhdGgsIkZyZXFDZWxsVHlwZXMyaW5GQUNTLmNzdiIpKQoKYGBgCgoKClByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiBvcmlnaW5hbCBGQUNTIHBvcHVsYXRpb25zCgoKYGBge3J9CgojIG9yaWdpbmFsIGNsdXN0ZXJzIHByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiAKbGlicmFyeShyZXNoYXBlMikKCnByLmNlbGx0eXBlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKG5ldXJvbnMuZGEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsbmV1cm9ucy5kYSRvcmlnLmlkZW50KSkKcHIuY2VsbHR5cGVzIDwtIHJlc2hhcGUocHIuY2VsbHR5cGVzLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpwci5jZWxsdHlwZXMKcHIgPC0gcHIuY2VsbHR5cGVzICU+JSBzZWxlY3QoVmFyMixgRnJlcS5EQU5ldXJvbnMtUkFCM0JgLGBGcmVxLkRBTmV1cm9ucy1UUEJHYCxgRnJlcS5EQU5ldXJvbnMtVFRSYCkKcHIKcHIgPC0gdChwcikKcHIKd3JpdGUuY3N2KHByLCBwYXN0ZShvdXRwdXRfcGF0aCwiQ2VsbENvdW50c0RBbmV1cm9uc1BlckZBQ1Nwb3AuY3N2IikpCgoKYGBgCgoKUHJvcG9ydGlvbiBvZiBjZWxsIHR5cGVzIHRlc3RzCgpgYGB7cn0KCmxpYnJhcnkoInNjUHJvcG9ydGlvblRlc3QiKQoKcHJvcF90ZXN0IDwtIHNjX3V0aWxzKHNldS5zYykKCnByb3BfdGVzdCA8LSBwZXJtdXRhdGlvbl90ZXN0KAoJcHJvcF90ZXN0LCBjbHVzdGVyX2lkZW50aXR5ID0gIkNlbGxfVHlwZTIiLAoJc2FtcGxlXzEgPSAiTmV1cm9uczEiLCBzYW1wbGVfMiA9ICJOZXVyb25zMiIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQoKCnBlcm11dGF0aW9uX3Bsb3QocHJvcF90ZXN0KQoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJOZXVyb25zMSIsIHNhbXBsZV8yID0gIlJhZGlhbEdsaWEiLAoJc2FtcGxlX2lkZW50aXR5ID0gIm9yaWcuaWRlbnQiCikKcGVybXV0YXRpb25fcGxvdChwcm9wX3Rlc3QpCgoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJOZXVyb25zMiIsIHNhbXBsZV8yID0gIlJhZGlhbEdsaWEiLAoJc2FtcGxlX2lkZW50aXR5ID0gIm9yaWcuaWRlbnQiCikKcGVybXV0YXRpb25fcGxvdChwcm9wX3Rlc3QpCgoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJBc3Ryb2N5dGVzIiwgc2FtcGxlXzIgPSAiUmFkaWFsR2xpYSIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQpwZXJtdXRhdGlvbl9wbG90KHByb3BfdGVzdCkKCmBgYAoKCkNoZWNrIHRoZSBwcm9wb3J0aW9ucyBvZiBzdWJ0eXBlcyBvZiBEQSBuZXVyb25zCgpgYGB7cn0KCiNsaWJyYXJ5KCJzY1Byb3BvcnRpb25UZXN0IikKCnByb3BfdGVzdCA8LSBzY191dGlscyhuZXVyb25zLmRhKQoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9TdWJ0eXBlX01hcmtlcnMiLAoJc2FtcGxlXzEgPSAiTmV1cm9uczEiLCBzYW1wbGVfMiA9ICJOZXVyb25zMiIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQoKCnBlcm11dGF0aW9uX3Bsb3QocHJvcF90ZXN0KQoKYGBgCgoKRGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBiZXR3ZWVuIE5ldXJvbnMxIGFuZCBOZXVyb25zMiBmb3IgT3RoZXIgbmV1cm9ucyBhbmQgREEgbmV1cm9ucy4gCgpgYGB7cn0KSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfVHlwZTInCnN1Yi5uZXVyIDwtIHN1YnNldChzZXUuc2MsIGlkZW50cyA9ICJOZXVyb25zIikKRGltUGxvdChzdWIubmV1ciwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKQoKSWRlbnRzKHN1Yi5uZXVyKSA8LSAnb3JpZy5pZGVudCcKZGVnLm5ldXJvbnMgPC0gRmluZE1hcmtlcnMoc3ViLm5ldXIsIGlkZW50LjEgPSAiTmV1cm9uczEiLCBpZGVudC4yID0gIk5ldXJvbnMyIikKCnVwIDwtIHJvd25hbWVzKGRlZy5uZXVyb25zICU+JSBmaWx0ZXIoYXZnX2xvZzJGQyA+IDEuMikpCmxlbmd0aCh1cCkKCmRvd24gPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihhdmdfbG9nMkZDIDwgLTYpKQpsZW5ndGgoZG93bikKCnVwLmRvd24gPC0gYyh1cCxkb3duKQoKRG9IZWF0bWFwKHN1Yi5uZXVyLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSB1cC5kb3duKQoKdXAKZG93bgoKCiMgdXAgaXMgaW4gbmV1cm9uczEgYW5kIGRvd24gaXMgaW4gbmV1cm9uczIKCndyaXRlLmNzdihkZWcubmV1cm9ucywgcGFzdGUob3V0cHV0X3BhdGgsICJERUcubmV1cm9uczF2c25ldXJvbnMyaW5OZXVyb25zLmNzdiIpKQoKCmBgYAoKCgpJbiBEQSBuZXVyb25zCgpgYGB7cn0KCklkZW50cyhzZXUuc2MpIDwtICdDZWxsX1R5cGUyJwpzdWIubmV1ciA8LSBzdWJzZXQoc2V1LnNjLCBpZGVudHMgPSAiREFOZXVyb25zIikKRGltUGxvdChzdWIubmV1ciwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKQoKSWRlbnRzKHN1Yi5uZXVyKSA8LSAnb3JpZy5pZGVudCcKZGVnLm5ldXJvbnMuZGEgPC0gRmluZE1hcmtlcnMoc3ViLm5ldXIsIGlkZW50LjEgPSAiTmV1cm9uczEiLCBpZGVudC4yID0gIk5ldXJvbnMyIikKCnVwIDwtIHJvd25hbWVzKGRlZy5uZXVyb25zICU+JSBmaWx0ZXIoYXZnX2xvZzJGQyA+IDEuMikpCmxlbmd0aCh1cCkKCmRvd24gPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihhdmdfbG9nMkZDIDwgLTAuNSkpCmxlbmd0aChkb3duKQpkb3duCmRvd24gPC0gZG93blsxNzozNl0KdXAuZG93biA8LSBjKHVwLGRvd24pCgpEb0hlYXRtYXAoc3ViLm5ldXIsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHVwLmRvd24pCgpEb3RQbG90KHN1Yi5uZXVyLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSB1cC5kb3duKSArIFJvdGF0ZWRBeGlzKCkKCndyaXRlLmNzdihkZWcubmV1cm9ucy5kYSwgcGFzdGUob3V0cHV0X3BhdGgsICJERUcubmV1cm9uczF2c25ldXJvbnMyaW5EQU5ldXJvbnMuY3N2IikpCgoKYGBgCgoKTG9vayBhdCB0aGUgR08gYW5kIG90aGVyIHBhdGh3YXkgYW5hbHlzaXMgZm9yIHRoZSBER0UKCmBgYHtyfQoKIyBmb3IgbmV1cm9ucwoKbGlicmFyeShlbnJpY2hSKQoKc2V0RW5yaWNoclNpdGUoIkVucmljaHIiKSAjIEh1bWFuIGdlbmVzCiMgbGlzdCBvZiBhbGwgdGhlIGRhdGFiYXNlcwoKIyBsaWJhcmllcyB3aXRoIGNlbGwgdHlwZXMKI2RicyA8LSBsaXN0RW5yaWNockRicygpCiNkYnMKZGIgPC0gYygnR09fQ2VsbHVsYXJfQ29tcG9uZW50XzIwMTgnLCdHT19CaW9sb2dpY2FsX1Byb2Nlc3NfMjAxOCcsCiAgICAgICAgJ0dPX01vbGVjdWxhcl9GdW5jdGlvbl8yMDE4JykKCk5ldXJvbnMxLnVwIDwtIGRlZy5uZXVyb25zICU+JSBmaWx0ZXIocF92YWxfYWRqIDwgMC4wNSAmIGF2Z19sb2cyRkMgPiAwKQpnZW5lcyA8LSByb3duYW1lcyhOZXVyb25zMS51cCkKCkVyIDwtIGVucmljaHIoZ2VuZXMsIGRhdGFiYXNlcyA9IGRiKQpwcmludChwbG90RW5yaWNoKEVyW1sxXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIlAudmFsdWUiKSkKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzNdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiUC52YWx1ZSIpKQoKbGlicmFyeShkcGx5cikKdC5HT2NlbGwubiA8LSBFcltbMV1dIAp0LkdPYmlvLm4gPC0gRXJbWzJdXSAKdC5HT21vbC5uIDwtIEVyW1szXV0gCiMgc3lucGF0aGV0aWMgbmV1cnZvdXMgc3l0ZW0gZGV2CiMgCUZaRDM7Q1ROTkIxO1NPWDExO0FTQ0wxO1NPWDQKI25lZ2F0aXZlIHJlZ3VsYXRpb24gb2YgbmV1cm9uIGRpZmZlcmVudGlhdGlvbiAoR086MDA0NTY2NSkKIyAJRUZOQjI7SUQyO0lEMTtJRDM7SEVTMTtTT1g5O0NBTFI7QVNDTDEKCiMgbmVnYXRpdmUgcmVndWxhdGlvbiBvZiBuZXVyb2dlbmVzaXMgKEdPOjAwNTA3NjgpCiMgSUQyO0lEMTtJRDM7UEFYNjtDQUxSO0FTQ0wxCgojIG5ldXJvbmFsIGRpZmZlcmVudGlhdGlvbgojIAlGWkQzO0lEMjtJRDE7SUQzO0NUTk5CMTtTT1gxMTtPVFgyO1BBWDY7QVNDTDE7U09YNAoKIyAJSUQyO0lEMTtJRDM7U09YMTE7VENGNDtDQUxSO0FTQ0wxCgoKTmV1cm9uczIudXAgPC0gZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihwX3ZhbF9hZGogPCAwLjA1ICYgYXZnX2xvZzJGQyA8IDApCmdlbmVzIDwtIHJvd25hbWVzKE5ldXJvbnMyLnVwKQoKRXIgPC0gZW5yaWNocihnZW5lcywgZGF0YWJhc2VzID0gZGIpCnByaW50KHBsb3RFbnJpY2goRXJbWzFdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiUC52YWx1ZSIpKQpwcmludChwbG90RW5yaWNoKEVyW1syXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIlAudmFsdWUiKSkKcHJpbnQocGxvdEVucmljaChFcltbM11dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCgoKdC5HT2NlbGwuZCA8LSBFcltbMV1dICMlPiUgc2VsZWN0KFRlcm0sIEdlbmVzLCBDb21iaW5lZC5TY29yZSkKdC5HT2Jpby5kIDwtIEVyW1syXV0gIyU+JSBzZWxlY3QoVGVybSwgR2VuZXMsIENvbWJpbmVkLlNjb3JlKQp0LkdPbW9sLmQgPC0gRXJbWzNdXSAjJT4lIHNlbGVjdChUZXJtLCBHZW5lcywgQ29tYmluZWQuU2NvcmUpCiAKCiMgZ28gYmlvbG9naWNhbCB0ZXJtcyBhcmUgdGhlIG1vc3QgaW50ZXJlc3RpbmcgCiAgCiAgCiAgIyBuZXVyb25zMiB1cCAKICAjCiAgCiAgCiAgCgoKCmBgYAoKRm9yIERBIG5ldXJvbnMgCgpgYGB7cn0KCnNldEVucmljaHJTaXRlKCJFbnJpY2hyIikgIyBIdW1hbiBnZW5lcwojIGxpc3Qgb2YgYWxsIHRoZSBkYXRhYmFzZXMKCiMgbGliYXJpZXMgd2l0aCBjZWxsIHR5cGVzCiNkYnMgPC0gbGlzdEVucmljaHJEYnMoKQojZGJzCmRiIDwtIGMoJ0dPX0NlbGx1bGFyX0NvbXBvbmVudF8yMDE4JywnR09fQmlvbG9naWNhbF9Qcm9jZXNzXzIwMTgnLAogICAgICAgICdHT19Nb2xlY3VsYXJfRnVuY3Rpb25fMjAxOCcpCgpOZXVyb25zMS51cCA8LSBkZWcubmV1cm9ucyAlPiUgZmlsdGVyKHBfdmFsX2FkaiA8IDAuMDUgJiBhdmdfbG9nMkZDID4gMCkKZ2VuZXMgPC0gcm93bmFtZXMoTmV1cm9uczEudXApCgpFciA8LSBlbnJpY2hyKGdlbmVzLCBkYXRhYmFzZXMgPSBkYikKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJPZGRzLlJhdGlvIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQWp1c3RlZC5QLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSkKCgp0LkdPYmlvLmRhMSA8LSBFcltbMl1dIAoKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKQpwbG90RW5yaWNoKHQuR09iaW8uZGExLCBzaG93VGVybXMgPSAxMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJPdmVybGFwIikKCiMgCUVGTkIyO0lEMjtJRDE7SUQzO0hFUzE7U09YOTtDQUxSO0FTQ0wxCiMgbmV1cm9uYWwgZGlmZmVyZW50aWF0aW9uCiMgCUZaRDM7SUQyO0lEMTtJRDM7Q1ROTkIxO1NPWDExO09UWDI7UEFYNjtBU0NMMTtTT1g0Ck5ldXJvbnMyLnVwIDwtIGRlZy5uZXVyb25zICU+JSBmaWx0ZXIocF92YWxfYWRqIDwgMC4wNSAmIGF2Z19sb2cyRkMgPCAwKQpnZW5lcyA8LSByb3duYW1lcyhOZXVyb25zMi51cCkKCkVyIDwtIGVucmljaHIoZ2VuZXMsIGRhdGFiYXNlcyA9IGRiKQpwcmludChwbG90RW5yaWNoKEVyW1syXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIk9kZHMuUmF0aW8iKSkKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSkKdC5HT2Jpby5kYTIgPC0gRXJbWzJdXSAKCiMgbWFueSBNVCBnZW5lLCBhbHNvICJGVEgxIiwiRlRMIiwiQVBPRSIsIlNBVDEiLCJQVE4iLCJHQUJBUkFQIiwiUFRHRFMiCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkdPcmVzdWx0ZXNOZXVyb25zMXZzMi5wZGYiKSwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiT3ZlcmxhcCIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCnBsb3RFbnJpY2godC5HT2Jpby5kYTIsIHNob3dUZXJtcyA9IDEwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIkNvbWJpbmVkLlNjb3JlIikrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKcGxvdEVucmljaCh0LkdPYmlvLmRhMiwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiT3ZlcmxhcCIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCmRldi5vZmYoKQoKCmBgYAoKCkRvdCBwbG90cyBvZiBzb21lIHVwIHJlZ3VsYXRlZCBnZW5lcwoKYGBge3J9CgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9UeXBlMicKYWxsLm5ldXJvbnMgPC0gc3Vic2V0KHNldS5zYyxpZGVudHMgPSBjKCJEQU5ldXJvbnMiLCJOZXVyb25zIikgKQoKSWRlbnRzKGFsbC5uZXVyb25zKSA8LSAnb3JpZy5pZGVudCcKYWxsLm5ldXJvbnMgPC0gc3Vic2V0KGFsbC5uZXVyb25zLGlkZW50cyA9IGMoIk5ldXJvbnMxIiwiTmV1cm9uczIiKSApCgojIAlGWkQzO0lEMjtJRDE7SUQzO0NUTk5CMTtTT1gxMTtPVFgyO1BBWDY7QVNDTDE7U09YNAoKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkNUTk5CMSIsIlNPWDExIiwiQVNDTDEiLCJTT1g0IiwiSUQyIiwiSUQxIiwiSUQzIiwKICAgICAgICAgICAgICAgICAgICAiVENGNCIsIkNBTFIiLCJPVFgyIiwiUEFYNiIsIkhFUzEiLCJTT1g5IikKCiMgbWFya2VycyB1cCBpbiBuZXVyb25zMSAtIHdpdGggY2hhbmdlIGluIGJvdGggREEgYW5kIG90aGVyIG5ldXJvbnMKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkNUTk5CMSIsIlNPWDExIiwiQVNDTDEiLCJTT1g0IiwKICAgICAgICAgICAgICAgICAgICAiVENGNCIsIkNBTFIiLCJPVFgyIiwiUEFYNiIsIkVGTkIyIiwgCiAgICAgICAgICAgICAgICAgICAgIkNEMjQiLCJLQ05RMU9UMSIsIkNDTkcyIiwiSEVTNiIpCgojIHRvcCB1cCBpbiBuZXVyb25zIDEgCiMgIkNEMjQiICAgICAiS0NOUTFPVDEiICJDQ05HMiIgICAgIkFTQ0wxIiAgICAiSEVTNiIgCgojIHNlbGVjdGVkIHVwIHJlZ3VsYXRlZCBpbiBOZXVyb25zIDEKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkFTQ0wxIiwiU09YNCIsCiAgICAgICAgICAgICAgICAgICAgIlRDRjQiLCJDQUxSIiwiUEFYNiIsIAogICAgICAgICAgICAgICAgICAgICJDRDI0IiwiS0NOUTFPVDEiLCJDQ05HMiIpCgpEb3RQbG90KGFsbC5uZXVyb25zLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSByZWd1bGF0ZS5nZW5lcywKICAgICAgICBzcGxpdC5ieSA9ICdDZWxsX1R5cGUyJykgKyBSb3RhdGVkQXhpcygpCiMgYWxsIHRoZSBleHByZXNzaW9uIGxldmVscyBhcmUgbG93ZXIgaW4gcmVndWxhciBuZXVyb25zIHRoYW4gREEgbmV1cm9ucwoKRG90UGxvdChhbGwubmV1cm9ucywgZ3JvdXAuYnkgPSAnb3JpZy5pZGVudCcsIGZlYXR1cmVzID0gcmVndWxhdGUuZ2VuZXMpICsgUm90YXRlZEF4aXMoKQoKIyB1cCByZWcgaW4gTmV1cm9uczIKIyBtYW55IE1UIGdlbmUsIGFsc28gIkZUSDEiLCJGVEwiLCJBUE9FIiwiU0FUMSIsIlBUTiIsIkdBQkFSQVAiLCJQVEdEUyIKCiMgdG9wIHVwIHJlZyBnZW5lcyBpbiBOZXVyb25zMgojIk1BTEFUMSIgICJNVC1ORDIiICAiTVQtQ08xIiAgIk1ULUNPMiIgICJNVC1BVFA2IiAiTVQtQ08zIiAgIk1ULU5EMyIgICJNVC1DWUIiIAoKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlRIMSIsIkZUTCIsIkFQT0UiLCJTQVQxIiwiUFROIiwiR0FCQVJBUCIsIlBUR0RTIiwiU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICAgIlJQTDE3IiwiTVRSTlIyTDEyIiwiTVRSTlIyTDgiLCJTTkhHMjUiLCJTRUxFTk9XIiwKICAgICAgICAgICAgICAgICAgICAiQ1JZQUIiLCAiUEVBMTUiLCAiQVRQMUEyIiwgIlNFTEVOT0siLCJJR0ZCUDciLCAiUkFCM0IiKQojIHN0cm9uZ2x5IGFsdGVyZWQgZ2VuZXMKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlRIMSIsIkZUTCIsIlBUTiIsIlBUR0RTIiwiU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICAgIlNFTEVOT1ciLCJDUllBQiIsICJNQUxBVDEiLCAiTVQtTkQyIiwgIk1ULUNPMSIsICJNVC1DTzIiLAogICAgICAgICAgICAgICAgICAgICJNVC1BVFA2IiwgIk1ULUNPMyIsICJNVC1ORDMiLCAiTVQtQ1lCIikKcmVndWxhdGUuZ2VuZXMgPC0gYygiTVQtTkQyIiwgIk1ULUNPMSIsICJNVC1DTzIiLAogICAgICAgICAgICAgICAgICAgICJNVC1BVFA2IiwgIk1ULUNPMyIsICJNVC1ORDMiLAogICAgICAgICAgICAgICAgICAgICJGVEgxIiwiRlRMIiwKICAgICAgICAgICAgICAgICAgICAiQ1JZQUIiKQoKIyBnZW5lcyB1cCBhbmQgZG93biAKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkFTQ0wxIiwiU09YNCIsCiAgICAgICAgICAgICAgICAgICAgIlRDRjQiLCJDQUxSIiwiUEFYNiIsIAogICAgICAgICAgICAgICAgICAgICJDRDI0IiwiS0NOUTFPVDEiLCJDQ05HMiIsIk1ULU5EMiIsICJNVC1DTzEiLCAiTVQtQ08yIiwKICAgICAgICAgICAgICAgICAgICAiTVQtQVRQNiIsICJNVC1DTzMiLCAiTVQtTkQzIiwKICAgICAgICAgICAgICAgICAgICAiRlRIMSIsIkZUTCIsCiAgICAgICAgICAgICAgICAgICAgIkNSWUFCIikKCkRvdFBsb3QoYWxsLm5ldXJvbnMsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHJlZ3VsYXRlLmdlbmVzKSArIFJvdGF0ZWRBeGlzKCkKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90UGxvdERFR19OMXZzTjIucGRmIikpCkRvdFBsb3QoYWxsLm5ldXJvbnMsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHJlZ3VsYXRlLmdlbmVzKSArIFJvdGF0ZWRBeGlzKCkKZGV2Lm9mZigpCgoKYGBgCgoKCgoKCgoKCmBgYHtyfQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2x1c3RlclByb2ZpbGVyIikKQmlvY01hbmFnZXI6Omluc3RhbGwoInBhdGh2aWV3IikKQmlvY01hbmFnZXI6Omluc3RhbGwoImVucmljaHBsb3QiKQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShlbnJpY2hwbG90KQojIHdlIHVzZSBnZ3Bsb3QyIHRvIGFkZCB4IGF4aXMgbGFiZWxzIChleDogcmlkZ2VwbG90KQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKCgpUcnkgd2l0aCBjbHVzdGVyIHByb2ZpbGVyCgpgYGB7cn0KCiMgbmVlZCBhIGdlbmUgbGlzdCBzb3J0ZWQgaW4gZGVjcmVhc2luZyBvcmRlcgojIGdldCB0aGUgbG9nMkZDCm9yaWdpbmFsX2dlbmVfbGlzdCA8LSBkZWcubmV1cm9ucyRhdmdfbG9nMkZDCiMgbmFtZSB0aGUgdmVjdG9yIC0gYWRkIHRoZSBnZW5lIG5hbWVzCm5hbWVzKG9yaWdpbmFsX2dlbmVfbGlzdCkgPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMpCmdlbmVfbGlzdCA9IG5hLm9taXQob3JpZ2luYWxfZ2VuZV9saXN0KQoKZ2VuZV9saXN0ID0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBnZXQgdGhlIGdlbmUgc2V0IGVucmljaG1lbnQgbGlzdApsaWJyYXJ5KG9yZy5Icy5lZy5kYikKCmdzZSA8LSBnc2VHTyhnZW5lTGlzdD1nZW5lX2xpc3QsIAogICAgICAgICAgICAgb250ID0iQlAiLCAKICAgICAgICAgICAgIGtleVR5cGUgPSAiU1lNQk9MIiwgCiAgICAgICAgICAgICBtaW5HU1NpemUgPSAzLCAKICAgICAgICAgICAgIG1heEdTU2l6ZSA9IDgwMCwgCiAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFLCAKICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAibm9uZSIpCgpyZXF1aXJlKERPU0UpCmRvdHBsb3QoZ3NlLCBzaG93Q2F0ZWdvcnk9MjAsIHNwbGl0PSIuc2lnbiIpICsgZmFjZXRfZ3JpZCgufi5zaWduKQoKZW1hcHBsb3QoZ3NlLCBzaG93Q2F0ZWdvcnkgPSAxMCkKCmBgYAoKClByZWRpY3QgY2VsbCB0eXBlcyBhZ2FpbiB0byBtYWtlIHRhYmxlIDEyCk9yZ2Fub2lkcyBpbiBob3VzZSBkYXRhCgpgYGB7cn0KCnBhdGh3YXkgPC0gIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL1BoZW5vSUQvc2NSTkFzZXFTb3J0ZWQvb2Jqcy8iCnNldS5zYyA8LSByZWFkUkRTKHBhc3RlKHBhdGh3YXksICJDb21iaW5lZExhYmVsZWRNYXJrZXJzMTQxMDIwMjIuUkRTIikpCgojIHByZWRpY3Qgd2l0aCBBSVcKIyBTTkNBIGFuZCBjb250cm9sIG1pZGJyYWluIG9yZ2Fub2lkcyAxNjUgZGF5cyBpbiBjdWx0dXJlCkFTVDIzIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL0FTVDIzX0JyYWluQ29tbS9NQk9jbHVzdGVyc19uYW1lczI5MDcyMDIxLnJkcyIpCgojIE1pZGJyYWluICBBSVcwMDIgMTIwIGRheXMgaW4gY3VsdHVyZQpBSVcxMjAgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvQUlXdHJpbzEyMGRheXMvTU9pbnRlZ3JhdGVkQ2x1c3RlcksxMjNyZXMwLjgubmFtZXNfbm92MTZfMjAyMSIpCgojIE1pZGJyYWluIEFJVzAwMiA2MCBkYXlzIGluIGN1bHR1cmUKCkFJVzYwIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL0FJV3RyaW82MGRheXMvQVdJMDAyUGFya2luS09QaW5rS082MGRheXNfbGFiZWxzXzE0MDUyMDIyLnJkcyIpCgoKIyBBU1QyMwpzZXUuciA8LSBBU1QyMwpzZXUucSA8LSBzZXUuc2MKCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByaW50KCJnZXR0aW5nIHByZWRpY3Rpb25zIikKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRjbHVzdGVyX2xhYmVscywgay53ZWlnaHQgPSA1MCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJEFTVDIzLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCgpEaW1QbG90KHNldS5xLCBncm91cC5ieSA9ICdBU1QyMy5wcmVkJykKCiMgQUlXIDYwCnNldS5yIDwtIEFJVzYwCmNvbG5hbWVzKHNldS5yQG1ldGEuZGF0YSkKCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByaW50KCJnZXR0aW5nIHByZWRpY3Rpb25zIikKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRjbHVzdGVyLmlkcywgay53ZWlnaHQgPSA1MCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJEFJVzYwLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FJVzYwLnByZWQnKQoKCiMgQUlXIDEyMApzZXUuciA8LSBBSVcxMjAKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJHJlczA4bmFtZXMyLCBrLndlaWdodCA9IDUwKQpzZXUucSA8LSBBZGRNZXRhRGF0YShzZXUucSwgcHJlZGljdGlvbnMkcHJlZGljdGVkLmlkLCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uIikKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3Rpb24uc2NvcmUubWF4LCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uLnNjb3JlLm1heCIpCgoKc2V1LnEkQUlXMTIwLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC44LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FJVzEyMC5wcmVkJykKCgoKYGBgCgoKTW9yZSBwcmVkaWN0aW9ucyAKRGV2ZWxvcGluZyBicmFpbjogQ29ydGV4CiAgICAgICAgICAgICAgICAgIEZvcmVicmFpbgoKQWR1bHQgYnJhaW46IHdob2xlIGJyYWluIHdpdGggc3VidHlwZXMKQWR1bHQgYnJhaW4gbWlkYnJhaW4gYW5kIHN0cmlhdHVtCkFkdWx0IGJyYWluIG1pZGJyYWluIG1haW4gY2VsbCB0eXBlcwpBZHVsdCBicmFpbiBEQSBvciBBc3RybyBzdWJ0eXBlcwoKCmBgYHtyfQoKCkRBc3VidHlwZXMgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvTWFjb3Nrb19EYXRhL0RBc3ViZ3JvdXBzX3Byb2Nlc3NlZC5SZHMiKQoKCnNldS5yIDwtIERBc3VidHlwZXMKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJENlbGxfU3VidHlwZSwgay53ZWlnaHQgPSAyMCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJERBc3ViLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0RBc3ViLnByZWQnKQoKCiMgYXN0cm9jeXRlcwoKYXN0cm8ucmVmIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL01hY29za29fRGF0YS9QRF9hc3Ryby5SZHMiKQojIG5lZWQgdG8gbWFrZSBQQ0EgYW5kIFVNQVAKYXN0cm8ucmVmIDwtIE5vcm1hbGl6ZURhdGEoYXN0cm8ucmVmKQphc3Ryby5yZWYgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYXN0cm8ucmVmLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCmFzdHJvLnJlZiA8LSBTY2FsZURhdGEoYXN0cm8ucmVmKQphc3Ryby5yZWYgPC0gUnVuUENBKGFzdHJvLnJlZikKYXN0cm8ucmVmIDwtIFJ1blVNQVAoYXN0cm8ucmVmLCByZWR1Y3Rpb24gPSAicGNhIiwgbi5uZWlnaGJvcnMgPSAyMDUsIGRpbXMgPSAxOjI1KQoKCnNldS5yIDwtIGFzdHJvLnJlZgoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJENlbGxfU3VidHlwZSwgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRBc3Ryby5zdWIgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC44LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FzdHJvLnN1YicpCgoKIyBNaWRicmFpbiBhbmQgU3RyaWF0dW0gCgpzZXUuciA8LSByZWFkUkRTKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9zY1JOQXNlcS9QdWJsaWNEYXRhL0JoYWR1cmlfbWlkYnJhaW5fc3RyaWF0dW0uUkRTIikKCiMgd2hvbGUgYnJhaW4Kc2V1LnIgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUHVibGljRGF0YS9CaGFkdXJpX2Rvd25zYW1wbGUuUkRTIikKCgpJZGVudHMoc2V1LnIpIDwtICJjZWxsX2NsdXN0ZXIiCgojIGZpbmQgdGhlIHJlZmVyZW5jZSBhbmNob3JzCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByZWRpY3Rpb25zIDwtIFRyYW5zZmVyRGF0YShhbmNob3JzZXQgPSBhbmNob3JzLCByZWZkYXRhID0gc2V1LnIkY2VsbF9jbHVzdGVyLCBrLndlaWdodCA9IDI1KQpzZXUucSA8LSBBZGRNZXRhRGF0YShzZXUucSwgcHJlZGljdGlvbnMkcHJlZGljdGVkLmlkLCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uIikKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3Rpb24uc2NvcmUubWF4LCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uLnNjb3JlLm1heCIpCnNldS5xJEJyYWluIDwtIGlmZWxzZShzZXUucSRwcmVkaWN0aW9uLnNjb3JlLm1heCA+IDAuMywgc2V1LnEkcHJlZGljdGlvbiwgIm5vbmUiKQpEaW1QbG90KHNldS5xLCBncm91cC5ieSA9ICdCcmFpbicpCgoKIyBkZXZlbG9waW5nIGZvcmVicmFpbgoKc2V1LnIgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUHVibGljRGF0YS9LYXJvbGluc2tpX0RldkZvcmVicmFpbl9kb3duc2FtcGxlX0xldmVsMS5SRFMiKQpjb2xuYW1lcyhzZXUuckBtZXRhLmRhdGEpCklkZW50cyhzZXUucikgPC0gJ0NsdXN0ZXJzJwoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRDbHVzdGVycywgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRkZXZGb3JlYnJhaW4gPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC41LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ2RldkZvcmVicmFpbicpCgojIGRldmVsb3BpbmcgZm9yZWJyYWluCnNldS5yIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL1B1YmxpY0RhdGEvTm93YWtvd3NraV9kZXZfY29ydGV4dC5SRFMiKQoKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQpJZGVudHMoc2V1LnIpIDwtICdXR0NOQWNsdXN0ZXInCgphbmNob3JzIDwtIEZpbmRUcmFuc2ZlckFuY2hvcnMocmVmZXJlbmNlID0gc2V1LnIsIHF1ZXJ5ID0gc2V1LnEsIGRpbXMgPSAxOjI1KQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJFdHQ05BY2x1c3Rlciwgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRkZXZjb3J0ZXggPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC4zLCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ2RldmNvcnRleCcpCgpgYGAKCgoKClRhYmxlcyBvZiB0b3AgcHJlZGljdGlvbnMgCgpgYGB7cn0KI0FTVDIzCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQVNUMjMucHJlZCkpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgoKI0FJVyA2MAoKdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRBSVc2MC5wcmVkKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCgoKIyBBSVcgMTIwCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQUlXMTIwLnByZWQpKQp0LmxhYmxlcyRGcmVxIDwtIGFzLmRvdWJsZSh0LmxhYmxlcyRGcmVxKQoKCgojIERBIG5ldXJvbiBzdWJ0eXBlIHByZWRpY3Rpb25zCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkREFzdWIucHJlZCkpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgoKIyBBc3RybyBzdWJ0eXBlCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQXN0cm8uc3ViKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgTWlkYnJhaW4gQmhhZHVuaSBwcmVkaWN0aW9ucwp0LmxhYmxlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5xJENlbGxfU3VidHlwZV9NYXJrZXJzLHNldS5xJE1pZGJyYWluKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgd2hvbGUgYnJhaW4KdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRCcmFpbikpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgojIGRldmVsb3BpbmcgZm9yZWJyYWluCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkZGV2Rm9yZWJyYWluKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgZGV2ZWxvcGluZyBjb3J0ZXgKdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRkZXZjb3J0ZXgpKQp0LmxhYmxlcyRGcmVxIDwtIGFzLmRvdWJsZSh0LmxhYmxlcyRGcmVxKQoKdG9wLnByZWRpY3Rpb24gPC1hcy5kYXRhLmZyYW1lKHQubGFibGVzICAlPiUgZ3JvdXBfYnkoVmFyMSkgICU+JSB0b3BfbigxLCBGcmVxKSkKdG9wLnByZWRpY3Rpb24KCgoKCmBgYAoKCgoKCgo=